

package cn.shengchao.controler.pay;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.StrUtil;
import cn.shengchao.base.utils.HttpKit;
import cn.shengchao.cap.acl.ports.repositories.IProductThirdCapOrderGradeRepository;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeNodeInfoService;
import cn.shengchao.examstar.pay.model.service.fy.Const;
import cn.shengchao.examstar.pay.model.service.fy.FuYouUtil;
import cn.shengchao.examstar.pay.model.service.fy.Utils;
import cn.shengchao.examstar.pay.model.service.fy.dto.ParameterCollection;
import cn.shengchao.examstar.pay.ohs.local.message.CreateThirdCapRequestDTO;
import cn.shengchao.examstar.pay.ohs.local.message.CreateThirdYcRequestDTO;
import cn.shengchao.examstar.pay.utils.config.FyConfig;
import cn.shengchao.util.IPUtils;
import cn.shengchao.util.helper.LoginHelper;
import cn.shengchao.examstar.pay.acl.ports.client.ProductPayPrice;
import cn.shengchao.examstar.pay.model.entity.PayOrderEntity;
import cn.shengchao.examstar.pay.model.entity.ShopCartEntity;
import cn.shengchao.examstar.pay.model.service.IOrderService;
import cn.shengchao.examstar.pay.ohs.local.message.CreatePayRequestDTO;
import cn.shengchao.examstar.pay.utils.XXEInjectionGuardUtils;
import cn.shengchao.examstar.pay.utils.config.WxUtil;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import cn.shengchao.idempotent.annotation.Idempotent;

import java.io.BufferedReader;
import java.net.URLDecoder;
import java.util.Map;
import java.util.Objects;

@Tag(name = "支付")
@Slf4j
@RestController
@CrossOrigin("${project.cross-origin}")
@RequestMapping("/api/${project.version}/pay")
public class PayController {
    @Resource
    private IOrderService orderService;

    @Autowired
    private DistributeNodeInfoService distributeNodeInfoService;

    @Autowired
    private IProductThirdCapOrderGradeRepository productThirdCapOrderGradeRepository;
    @SaIgnore
    @GetMapping("get_appid_openid")
    public void appidOpenid(@RequestParam String baseUrl,@RequestParam String path) throws Exception {
        String url =
                FuYouUtil.wxAuthUrl(
                        baseUrl+"/#/"+path,
                        Map.of("k","1" ),
                        FyConfig.INS_CD,
                        FyConfig.MCHNT_CD,
                        FyConfig.INS_PRIVATE_KEY);
        HttpKit.getResponse().sendRedirect(url);
    }

    @SaIgnore
    @PostMapping("calculate")
    public ProductPayPrice calculate(@RequestBody CreatePayRequestDTO createPayRequestDTO) throws Exception {
        Long productId = createPayRequestDTO.getProductId();
        return orderService.calculate(ShopCartEntity.builder()
                .subProductIds(createPayRequestDTO.getSubProductIds())
                .shareCode(createPayRequestDTO.getShareCode())
                .productId(String.valueOf(productId))
                .build());
    }

    @Idempotent(timeout = 200)
    @RequestMapping(value = "create_pay_order", method = RequestMethod.POST)
    public Object createPayOrder(@RequestBody CreatePayRequestDTO createPayRequestDTO) throws Exception {
        Long userId = LoginHelper.getUserId();
        String openId = LoginHelper.getLoginUser().getOpenId();
        if (StrUtil.isNotBlank(createPayRequestDTO.getOpenid())) {
            openId = createPayRequestDTO.getOpenid();
        }
        Long productId = createPayRequestDTO.getProductId();
        String ip = IPUtils.getClientAddress(HttpKit.getRequest());
        log.info("商品下单，根据商品ID创建支付单开始 userId:{} productId:{}", userId, productId);
//        DistributeNodeInfo distributeNodeInfo = distributeNodeInfoService.getDistributeNodeInfoInCode(userId,
//                List.of(DistributeSaleRoleEnum.ROLE_MKMG, DistributeSaleRoleEnum.ROLE_DSPD, DistributeSaleRoleEnum.ROLE_SLMB));
//        CheckUtils.throwIf(distributeNodeInfo != null, "您已购买过此商品，请勿重复购买");
        // 下单
        PayOrderEntity payOrderEntity = orderService.createOrder(ShopCartEntity.builder()
                .userId(String.valueOf(userId))
                .subProductIds(createPayRequestDTO.getSubProductIds())
                .openId(openId)
                .appid(createPayRequestDTO.getAppid())
                .shareCode(createPayRequestDTO.getShareCode())
                .productId(String.valueOf(productId))
                .ip(ip)
                .type(createPayRequestDTO.getType())
                .build());
        log.info("商品下单，根据商品ID创建支付单完成 userId:{} productId:{} orderId:{}", userId, productId, payOrderEntity
                .getOrderId());

        return payOrderEntity.getPayInfo();
    }
    @Idempotent(timeout = 200)
    @RequestMapping(value = "create_third_cap_order", method = RequestMethod.POST)
    public Object createThirdCapOrder(@Validated @RequestBody CreateThirdCapRequestDTO createPayRequestDTO) throws Exception {
        Long userId = LoginHelper.getUserId();
        String openId = LoginHelper.getLoginUser().getOpenId();
        if (StrUtil.isNotBlank(createPayRequestDTO.getOpenid())) {
            openId = createPayRequestDTO.getOpenid();
        }
        Long productId = createPayRequestDTO.getProductId();
        String ip = IPUtils.getClientAddress(HttpKit.getRequest());
        log.info("第三方的高考志愿下单，根据商品ID创建支付单开始 userId:{} productId:{}", userId, productId);
       //不检查会员，第三方的，谁都要收钱
        //提交订单要提交毕业年份，所以这个年份本地需要保存，考虑保存【用户，订单号，年份】
        // 下单
        PayOrderEntity payOrderEntity = orderService.createOrder(ShopCartEntity.builder()
                .userId(String.valueOf(userId))
                .subProductIds(createPayRequestDTO.getSubProductIds())
                .openId(openId)
                .appid(createPayRequestDTO.getAppid())
                .shareCode(createPayRequestDTO.getShareCode())
                .productId(String.valueOf(productId))
                .ip(ip)
                .type(createPayRequestDTO.getType())
                .build());
        log.info("高考志愿下单，根据高考志愿下单服务ID创建支付单完成 userId:{} productId:{} orderId:{}", userId, productId, payOrderEntity
                .getOrderId());
        productThirdCapOrderGradeRepository.saveObj(payOrderEntity.getOrderId(), userId, createPayRequestDTO.getGraduationYear());
        return payOrderEntity.getPayInfo();
    }
    @Idempotent(timeout = 200)
    @RequestMapping(value = "create_third_ycbdc_order", method = RequestMethod.POST)
    public Object createThirdYcbdcOrder(@RequestBody CreateThirdYcRequestDTO createPayRequestDTO) throws Exception {
        Long userId = LoginHelper.getUserId();
        String openId = LoginHelper.getLoginUser().getOpenId();
        if (StrUtil.isNotBlank(createPayRequestDTO.getOpenid())) {
            openId = createPayRequestDTO.getOpenid();
        }
        Long productId = createPayRequestDTO.getProductId();
        String ip = IPUtils.getClientAddress(HttpKit.getRequest());
        log.info("第三方的忆成英语下单，根据商品ID创建支付单开始 userId:{} productId:{}", userId, productId);
        //不检查会员，第三方的，谁都要收钱
        //提交订单要提交毕业年份，所以这个年份本地需要保存，考虑保存【用户，订单号，年份】
        // 下单
        PayOrderEntity payOrderEntity = orderService.createOrder(ShopCartEntity.builder()
                .userId(String.valueOf(userId))
                .subProductIds(createPayRequestDTO.getSubProductIds())
                .openId(openId)
                .appid(createPayRequestDTO.getAppid())
                .shareCode(createPayRequestDTO.getShareCode())
                .productId(String.valueOf(productId))
                .ip(ip)
                .type(createPayRequestDTO.getType())
                .build());
        log.info("第三方的忆成英语下单，根据忆成英语下单服务ID创建支付单完成 userId:{} productId:{} orderId:{}", userId, productId, payOrderEntity
                .getOrderId());
        return payOrderEntity.getPayInfo();
    }
    /**
     * 微信小程序支付
     */
    @SaIgnore
    @RequestMapping(value = "wxXcxAsyncNotify/{orderId}", consumes = "text/xml", produces = "text/xml")
    public String wxXcxAsyncNotify(@RequestBody String xml, @PathVariable String orderId) throws Exception {
        XXEInjectionGuardUtils.xmlXXEGuard(xml);
        WxPayOrderNotifyResult wx = Objects.requireNonNull(WxUtil.WX_XCX_PAY_SERVICE).parseOrderNotifyResult(xml);
        if ("SUCCESS".equals(wx.getReturnCode()) && "SUCCESS".equals(wx.getResultCode())) {
            log.info("支付回调，用户标识：{}", wx.getOpenid());
            log.info("支付回调，交易类型：{}", wx.getTradeType());
            log.info("支付回调，是否关注公众号：{}", wx.getIsSubscribe());
            log.info("支付回调，付款银行:{}", wx.getBankType());
            log.info("支付回调，支付金额:{}", wx.getTotalFee());
            log.info("支付回调，微信支付单号:{}", wx.getTransactionId());
            log.info("支付回调，商户订单号:{}", wx.getOutTradeNo());
            log.info("支付回调，支付完成时间:{}", wx.getTimeEnd());
            // 更新订单未已支付
            orderService.changeOrderPaySuccess(orderId);
            return WxPayNotifyResponse.success("成功!");
        } else {
            log.error("【微信支付异步通知】发起支付, returnCode != SUCCESS, returnMsg = " + wx.getReturnMsg(), xml);
            return WxPayNotifyResponse.fail("失败!");
        }
    }

    /**
     * 微信小程序支付
     */
    @SaIgnore
    @RequestMapping(value = "fyAsyncNotify/{orderId}")
    public int fyAsyncNotify(@PathVariable String orderId) throws Exception {
        StringBuilder data = new StringBuilder();
        String line;
        BufferedReader reader;
        reader = HttpKit.getRequest().getReader();
        while (null != (line = reader.readLine())) {
            data.append(line);
        }
        String jsonSt = data.toString();
        String req=jsonSt.replace("req=","");
        String rspXml = URLDecoder.decode(URLDecoder.decode(req, Const.charset),Const.charset);
        log.info("【富友支付异步通知】:{}", rspXml);
        ParameterCollection resMap = Utils.xmlToParameterCollection(rspXml);
        if (Utils.verifySign(resMap, resMap.getValue("sign"), FyConfig.FY_PUBLIC_KEY)) {
            if(resMap.getValue("result_msg").equals("SUCCESS")) {
                log.info("【富友支付异步通知】支付成功:{}", rspXml);
                // 更新订单未已支付
                orderService.changeOrderPaySuccess(orderId);
                return 1;
            }
        }
            log.error("【富友支付异步通知】支付失败:{}", req);
            return 0;
    }
}
